"""
数据质量插件单元测试
"""
import unittest
import numpy as np
import sys
import os
from unittest.mock import Mock, patch

# 添加src目录到Python路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from plugins.data_quality.data_quality import (
    DataContinuity, DataEmptyValue, DataOutOfRange, DataMeanStatistics,
    DataMedianStatistics, DataStdStatistics, DataSkewnessStatistics, DataKurtosisStatistics,
    DataCategoryStatistics
)
from plugins.base_plugin import BasePlugin


class TestDataQualityPlugins(unittest.TestCase):
    """测试数据质量插件"""

    def setUp(self):
        """设置测试环境"""
        # 模拟插件配置
        self.mock_config = {
            "config": {
                "column_name": "timestamp",
                "interval": 60,
                "threshold_upper": 100.0,
                "threshold_lower": 0.0,
                "column_names": ["value1", "value2"],
                "threshold_range": [[0.0, 100.0], [10.0, 50.0]]
            }
        }

    def test_data_continuity_normal_data(self):
        """测试数据连续性检查 - 正常数据"""
        # 创建插件实例
        plugin = DataContinuity("test_continuity", self.mock_config)
        
        # 准备测试数据 - 连续的时间戳
        test_data = [
            {"timestamp": 1000, "value": 10},
            {"timestamp": 1060, "value": 20},
            {"timestamp": 1120, "value": 30},
            {"timestamp": 1180, "value": 40}
        ]
        
        # 执行测试
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["missing_rate"], 0.0)
        self.assertEqual(len(result["missing_points"]), 0)
        self.assertEqual(result["continuity_check_by"], "test_continuity")

    def test_data_continuity_with_gaps(self):
        """测试数据连续性检查 - 存在间隔"""
        plugin = DataContinuity("test_continuity", self.mock_config)
        
        # 准备测试数据 - 存在时间戳间隔
        test_data = [
            {"timestamp": 1000, "value": 10},
            {"timestamp": 1060, "value": 20},
            {"timestamp": 1200, "value": 30},  # 间隔140，不是60
            {"timestamp": 1260, "value": 40}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["missing_rate"], 0.25)  # 1/4 = 0.25
        self.assertEqual(len(result["missing_points"]), 1)
        self.assertIn(1200, result["missing_points"])

    def test_data_continuity_missing_column(self):
        """测试数据连续性检查 - 缺少时间戳列"""
        plugin = DataContinuity("test_continuity", self.mock_config)
        
        # 准备测试数据 - 缺少timestamp列
        test_data = [
            {"value": 10},
            {"value": 20},
            {"value": 30}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果 - 由于没有有效的时间戳，缺失率为0
        self.assertEqual(result["missing_rate"], 0.0)
        self.assertEqual(len(result["missing_points"]), 0)

    def test_data_empty_value_with_empty_strings(self):
        """测试空值检查 - 空字符串"""
        plugin = DataEmptyValue("test_empty", {})
        
        # 准备测试数据 - 包含空字符串
        test_data = [
            {"col1": "data1", "col2": "data2"},
            {"col1": "", "col2": "data3"},  # 空字符串
            {"col1": "data4", "col2": "data5"}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["empty_rate"], 1/3)
        self.assertEqual(len(result["empty_points"]), 1)
        self.assertEqual(result["empty_check_by"], "test_empty")

    def test_data_empty_value_with_none_values(self):
        """测试空值检查 - None值"""
        plugin = DataEmptyValue("test_empty", {})
        
        # 准备测试数据 - 包含None值
        test_data = [
            {"col1": "data1", "col2": "data2"},
            {"col1": None, "col2": "data3"},  # None值
            {"col1": "data4", "col2": "data5"}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["empty_rate"], 1/3)
        self.assertEqual(len(result["empty_points"]), 1)

    def test_data_empty_value_with_nan_values(self):
        """测试空值检查 - NaN值"""
        plugin = DataEmptyValue("test_empty", {})
        
        # 准备测试数据 - 包含NaN值
        test_data = [
            {"col1": "data1", "col2": 10.0},
            {"col1": "data2", "col2": np.nan},  # NaN值
            {"col1": "data3", "col2": 20.0}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["empty_rate"], 1/3)
        self.assertEqual(len(result["empty_points"]), 1)

    def test_data_empty_value_no_empty_data(self):
        """测试空值检查 - 无空值"""
        plugin = DataEmptyValue("test_empty", {})
        
        # 准备测试数据 - 无空值
        test_data = [
            {"col1": "data1", "col2": 10.0},
            {"col1": "data2", "col2": 20.0},
            {"col1": "data3", "col2": 30.0}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["empty_rate"], 0.0)
        self.assertEqual(len(result["empty_points"]), 0)

    def test_data_out_of_range_normal_data(self):
        """测试超出范围检查 - 正常数据"""
        plugin = DataOutOfRange("test_range", self.mock_config)
        
        # 准备测试数据 - 数值在范围内
        test_data = [
            {"value1": 50.0, "value2": 20.0},  # 都在范围内
            {"value1": 75.0, "value2": 35.0},  # 都在范围内
            {"value1": 25.0, "value2": 45.0}   # 都在范围内
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["out_of_range_rate"], 0.0)
        self.assertEqual(len(result["out_of_range_points"]), 0)

    def test_data_out_of_range_with_violations(self):
        """测试超出范围检查 - 存在超出值"""
        plugin = DataOutOfRange("test_range", self.mock_config)
        
        # 准备测试数据 - 包含超出范围的值
        test_data = [
            {"value1": 50.0, "value2": 20.0},   # 正常
            {"value1": 150.0, "value2": 25.0},  # value1超出上限
            {"value1": 25.0, "value2": 55.0},   # value2超出上限
            {"value1": -10.0, "value2": 15.0}   # value1低于下限
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果
        self.assertEqual(result["out_of_range_rate"], 3/4)  # 3条记录有问题
        self.assertEqual(len(result["out_of_range_points"]), 3)

    def test_data_out_of_range_missing_columns(self):
        """测试超出范围检查 - 缺少配置列"""
        plugin = DataOutOfRange("test_range", self.mock_config)
        
        # 准备测试数据 - 缺少配置列
        test_data = [
            {"other_col": 50.0, "other_col2": 20.0},
            {"other_col": 75.0, "other_col2": 35.0}
        ]
        
        result = plugin.execute(test_data)
        
        # 验证结果 - 由于没有监控的列，超出率为0
        self.assertEqual(result["out_of_range_rate"], 0.0)
        self.assertEqual(len(result["out_of_range_points"]), 0)

    def test_plugin_input_data_formats(self):
        """测试插件处理不同输入数据格式"""
        plugin = DataEmptyValue("test_format", {})
        
        # 测试直接传入数据列表
        test_data = [
            {"col1": "data1", "col2": "data2"},
            {"col1": "", "col2": "data3"}
        ]
        
        result1 = plugin.execute(test_data)
        
        # 测试传入字典格式
        input_dict = {"raw_data": test_data}
        result2 = plugin.execute(input_dict)
        
        # 验证两种格式的结果相同
        self.assertEqual(result1["empty_rate"], result2["empty_rate"])
        self.assertEqual(len(result1["empty_points"]), len(result2["empty_points"]))

    @patch('plugins.data_quality.data_quality.logger')
    def test_plugin_logging(self, mock_logger):
        """测试插件日志记录"""
        plugin = DataEmptyValue("test_logging", {})
        
        test_data = [
            {"col1": "data1", "col2": "data2"},
            {"col1": "", "col2": "data3"}  # 空值
        ]
        
        plugin.execute(test_data)
        
        # 验证日志调用
        mock_logger.info.assert_called_with(f"Data empty rate: {1/2:.2f}")

    def test_data_mean_statistics_normal_data(self):
        """测试均值统计插件 - 正常数据"""
        test_data = [
            {"value": 10, "score": 80},
            {"value": 20, "score": 90},
            {"value": 30, "score": 85},
            {"value": 40, "score": 95},
            {"value": 50, "score": 88}
        ]
        
        plugin = DataMeanStatistics("test_mean", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("mean_statistics", result)
        self.assertIn("mean_statistics_check_by", result)
        # 验证均值计算（使用numpy验证）
        expected_value_mean = np.mean([10, 20, 30, 40, 50])
        expected_score_mean = np.mean([80, 90, 85, 95, 88])
        self.assertAlmostEqual(result["mean_statistics"]["value"], expected_value_mean, places=5)
        self.assertAlmostEqual(result["mean_statistics"]["score"], expected_score_mean, places=5)
        self.assertEqual(result["mean_statistics_check_by"], "test_mean")

    def test_data_mean_statistics_empty_data(self):
        """测试均值统计插件 - 空数据"""
        test_data = []
        
        plugin = DataMeanStatistics("test_mean", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("mean_statistics", result)
        self.assertIn("mean_statistics_check_by", result)
        self.assertEqual(result["mean_statistics"]["value"], None)
        self.assertEqual(result["mean_statistics_check_by"], "test_mean")

    def test_data_mean_statistics_missing_column(self):
        """测试均值统计插件 - 缺失列"""
        test_data = [
            {"value": 10},
            {"value": 20},
            {"value": 30}
        ]
        
        plugin = DataMeanStatistics("test_mean", {
            "config": {
                "column_names": ["value", "missing_column"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("mean_statistics", result)
        self.assertIn("mean_statistics_check_by", result)
        self.assertEqual(result["mean_statistics"]["value"], 20)  # (10+20+30)/3 = 20
        self.assertEqual(result["mean_statistics"]["missing_column"], None)
        self.assertEqual(result["mean_statistics_check_by"], "test_mean")

    def test_data_mean_statistics_single_value(self):
        """测试均值统计插件 - 单个值"""
        test_data = [
            {"value": 100}
        ]
        
        plugin = DataMeanStatistics("test_mean", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("mean_statistics", result)
        self.assertIn("mean_statistics_check_by", result)
        self.assertEqual(result["mean_statistics"]["value"], 100.0)  # 单个值均值就是其本身
        self.assertEqual(result["mean_statistics_check_by"], "test_mean")

    def test_data_mean_statistics_with_dict_input(self):
        """测试均值统计插件 - 字典格式输入"""
        test_data = {
            "raw_data": [
                {"value": 15, "score": 85},
                {"value": 25, "score": 90},
                {"value": 35, "score": 95}
            ]
        }
        
        plugin = DataMeanStatistics("test_mean", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("mean_statistics", result)
        self.assertIn("mean_statistics_check_by", result)
        expected_value_mean = np.mean([15, 25, 35])
        expected_score_mean = np.mean([85, 90, 95])
        self.assertAlmostEqual(result["mean_statistics"]["value"], expected_value_mean, places=5)
        self.assertAlmostEqual(result["mean_statistics"]["score"], expected_score_mean, places=5)
        self.assertEqual(result["mean_statistics_check_by"], "test_mean")


    def test_data_median_statistics_normal_data(self):
        """测试中位数统计插件 - 正常数据"""
        test_data = [
            {"value": 10, "score": 85},
            {"value": 20, "score": 90},
            {"value": 30, "score": 78},
            {"value": 40, "score": 92},
            {"value": 50, "score": 88}
        ]
        
        plugin = DataMedianStatistics("test_median", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("median_statistics", result)
        self.assertIn("median_statistics_check_by", result)
        self.assertEqual(result["median_statistics"]["value"], 30)  # 中位数
        self.assertEqual(result["median_statistics"]["score"], 88)  # 中位数
        self.assertEqual(result["median_statistics_check_by"], "test_median")

    def test_data_std_statistics_normal_data(self):
        """测试标准差统计插件 - 正常数据"""
        test_data = [
            {"value": 10, "score": 80},
            {"value": 20, "score": 90},
            {"value": 30, "score": 85},
            {"value": 40, "score": 95},
            {"value": 50, "score": 88}
        ]
        
        plugin = DataStdStatistics("test_std", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("std_statistics", result)
        self.assertIn("std_statistics_check_by", result)
        # 验证标准差计算（使用numpy验证）
        expected_value_std = np.std([10, 20, 30, 40, 50], ddof=1)
        expected_score_std = np.std([80, 90, 85, 95, 88], ddof=1)
        self.assertAlmostEqual(result["std_statistics"]["value"], expected_value_std, places=5)
        self.assertAlmostEqual(result["std_statistics"]["score"], expected_score_std, places=5)
        self.assertEqual(result["std_statistics_check_by"], "test_std")

    def test_data_skewness_statistics_normal_data(self):
        """测试偏度统计插件 - 正常数据"""
        # 正态分布数据（偏度接近0）
        test_data = [
            {"value": 10, "score": 85},
            {"value": 20, "score": 90},
            {"value": 30, "score": 78},
            {"value": 40, "score": 92},
            {"value": 50, "score": 88},
            {"value": 25, "score": 82},
            {"value": 35, "score": 95}
        ]
        
        plugin = DataSkewnessStatistics("test_skewness", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("skewness_statistics", result)
        self.assertIn("skewness_statistics_check_by", result)
        self.assertIsNotNone(result["skewness_statistics"]["value"])
        self.assertIsNotNone(result["skewness_statistics"]["score"])
        self.assertEqual(result["skewness_statistics_check_by"], "test_skewness")

    def test_data_kurtosis_statistics_normal_data(self):
        """测试峰度统计插件 - 正常数据"""
        # 正态分布数据（峰度接近0）
        test_data = [
            {"value": 10, "score": 85},
            {"value": 20, "score": 90},
            {"value": 30, "score": 78},
            {"value": 40, "score": 92},
            {"value": 50, "score": 88},
            {"value": 25, "score": 82},
            {"value": 35, "score": 95},
            {"value": 15, "score": 87}
        ]
        
        plugin = DataKurtosisStatistics("test_kurtosis", {
            "config": {
                "column_names": ["value", "score"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("kurtosis_statistics", result)
        self.assertIn("kurtosis_statistics_check_by", result)
        self.assertIsNotNone(result["kurtosis_statistics"]["value"])
        self.assertIsNotNone(result["kurtosis_statistics"]["score"])
        self.assertEqual(result["kurtosis_statistics_check_by"], "test_kurtosis")

    def test_data_kurtosis_statistics_insufficient_data(self):
        """测试峰度统计插件 - 数据不足"""
        test_data = [
            {"value": 10},
            {"value": 20},
            {"value": 30}
        ]
        
        plugin = DataKurtosisStatistics("test_kurtosis", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("kurtosis_statistics", result)
        self.assertIn("kurtosis_statistics_check_by", result)
        self.assertEqual(result["kurtosis_statistics"]["value"], None)  # 数据不足
        self.assertEqual(result["kurtosis_statistics_check_by"], "test_kurtosis")

    def test_data_kurtosis_statistics_empty_data(self):
        """测试峰度统计插件 - 空数据"""
        test_data = []
        
        plugin = DataKurtosisStatistics("test_kurtosis", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("kurtosis_statistics", result)
        self.assertIn("kurtosis_statistics_check_by", result)
        self.assertEqual(result["kurtosis_statistics"]["value"], None)
        self.assertEqual(result["kurtosis_statistics_check_by"], "test_kurtosis")

    def test_data_skewness_statistics_insufficient_data(self):
        """测试偏度统计插件 - 数据不足"""
        test_data = [
            {"value": 10},
            {"value": 20}
        ]
        
        plugin = DataSkewnessStatistics("test_skewness", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("skewness_statistics", result)
        self.assertIn("skewness_statistics_check_by", result)
        self.assertEqual(result["skewness_statistics"]["value"], None)  # 数据不足
        self.assertEqual(result["skewness_statistics_check_by"], "test_skewness")

    def test_data_skewness_statistics_empty_data(self):
        """测试偏度统计插件 - 空数据"""
        test_data = []
        
        plugin = DataSkewnessStatistics("test_skewness", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("skewness_statistics", result)
        self.assertIn("skewness_statistics_check_by", result)
        self.assertEqual(result["skewness_statistics"]["value"], None)
        self.assertEqual(result["skewness_statistics_check_by"], "test_skewness")

    def test_data_std_statistics_single_value(self):
        """测试标准差统计插件 - 单个值"""
        test_data = [
            {"value": 100}
        ]
        
        plugin = DataStdStatistics("test_std", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("std_statistics", result)
        self.assertIn("std_statistics_check_by", result)
        self.assertEqual(result["std_statistics"]["value"], 0.0)  # 单个值标准差为0
        self.assertEqual(result["std_statistics_check_by"], "test_std")

    def test_data_std_statistics_empty_data(self):
        """测试标准差统计插件 - 空数据"""
        test_data = []
        
        plugin = DataStdStatistics("test_std", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("std_statistics", result)
        self.assertIn("std_statistics_check_by", result)
        self.assertEqual(result["std_statistics"]["value"], None)
        self.assertEqual(result["std_statistics_check_by"], "test_std")

    def test_data_median_statistics_empty_data(self):
        """测试中位数统计插件 - 空数据"""
        test_data = []
        
        plugin = DataMedianStatistics("test_median", {
            "config": {
                "column_names": ["value"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("median_statistics", result)
        self.assertIn("median_statistics_check_by", result)
        self.assertEqual(result["median_statistics"]["value"], None)
        self.assertEqual(result["median_statistics_check_by"], "test_median")

    def test_data_median_statistics_missing_column(self):
        """测试中位数统计插件 - 缺失列"""
        test_data = [
            {"value": 10},
            {"value": 20},
            {"value": 30}
        ]
        
        plugin = DataMedianStatistics("test_median", {
            "config": {
                "column_names": ["value", "missing_column"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("median_statistics", result)
        self.assertIn("median_statistics_check_by", result)
        self.assertEqual(result["median_statistics"]["value"], 20)
        self.assertEqual(result["median_statistics"]["missing_column"], None)
        self.assertEqual(result["median_statistics_check_by"], "test_median")


    def test_data_category_statistics_normal_data(self):
        """测试类别统计插件 - 正常数据"""
        test_data = [
            {"category": "A", "type": "X", "value": 10},
            {"category": "B", "type": "X", "value": 20},
            {"category": "A", "type": "Y", "value": 30},
            {"category": "C", "type": "X", "value": 40},
            {"category": "A", "type": "X", "value": 50},
            {"category": "B", "type": "Y", "value": 60}
        ]
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["category", "type"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        self.assertIn("category_statistics_check_by", result)
        
        # 验证category列统计
        category_stats = result["category_statistics"]["category"]
        self.assertEqual(category_stats["total_categories"], 3)
        self.assertEqual(category_stats["category_counts"]["A"], 3)
        self.assertEqual(category_stats["category_counts"]["B"], 2)
        self.assertEqual(category_stats["category_counts"]["C"], 1)
        self.assertEqual(category_stats["most_frequent"], "A")
        self.assertEqual(category_stats["most_frequent_count"], 3)
        
        # 验证type列统计
        type_stats = result["category_statistics"]["type"]
        self.assertEqual(type_stats["total_categories"], 2)
        self.assertEqual(type_stats["category_counts"]["X"], 4)
        self.assertEqual(type_stats["category_counts"]["Y"], 2)
        self.assertEqual(type_stats["most_frequent"], "X")
        self.assertEqual(type_stats["most_frequent_count"], 4)
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")

    def test_data_category_statistics_numeric_categories(self):
        """测试类别统计插件 - 数值类别"""
        test_data = [
            {"status": 1, "priority": 1},
            {"status": 2, "priority": 1},
            {"status": 1, "priority": 2},
            {"status": 3, "priority": 1},
            {"status": 1, "priority": 3}
        ]
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["status", "priority"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        
        # 验证数值类别被正确转换为字符串
        status_stats = result["category_statistics"]["status"]
        self.assertEqual(status_stats["total_categories"], 3)
        self.assertEqual(status_stats["category_counts"]["1"], 3)  # 数值1被转换为字符串"1"
        self.assertEqual(status_stats["category_counts"]["2"], 1)
        self.assertEqual(status_stats["category_counts"]["3"], 1)
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")

    def test_data_category_statistics_with_none_values(self):
        """测试类别统计插件 - 包含None值"""
        test_data = [
            {"category": "A", "value": 10},
            {"category": None, "value": 20},  # None值
            {"category": "B", "value": 30},
            {"category": "A", "value": 40}
        ]
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["category"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        category_stats = result["category_statistics"]["category"]
        
        # None值被忽略，只统计非None值
        self.assertEqual(category_stats["total_categories"], 2)
        self.assertEqual(category_stats["category_counts"]["A"], 2)
        self.assertEqual(category_stats["category_counts"]["B"], 1)
        self.assertEqual(category_stats["most_frequent"], "A")
        self.assertEqual(category_stats["most_frequent_count"], 2)
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")

    def test_data_category_statistics_empty_data(self):
        """测试类别统计插件 - 空数据"""
        test_data = []
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["category"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        category_stats = result["category_statistics"]["category"]
        
        # 空数据情况下返回空统计
        self.assertEqual(category_stats["total_categories"], 0)
        self.assertEqual(category_stats["category_counts"], {})
        self.assertEqual(category_stats["most_frequent"], None)
        self.assertEqual(category_stats["most_frequent_count"], 0)
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")

    def test_data_category_statistics_missing_column(self):
        """测试类别统计插件 - 缺失列"""
        test_data = [
            {"existing_column": "A"},
            {"existing_column": "B"},
            {"existing_column": "A"}
        ]
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["existing_column", "missing_column"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        
        # 现有列正常统计
        existing_stats = result["category_statistics"]["existing_column"]
        self.assertEqual(existing_stats["total_categories"], 2)
        self.assertEqual(existing_stats["category_counts"]["A"], 2)
        self.assertEqual(existing_stats["category_counts"]["B"], 1)
        
        # 缺失列返回空统计
        missing_stats = result["category_statistics"]["missing_column"]
        self.assertEqual(missing_stats["total_categories"], 0)
        self.assertEqual(missing_stats["category_counts"], {})
        self.assertEqual(missing_stats["most_frequent"], None)
        self.assertEqual(missing_stats["most_frequent_count"], 0)
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")

    def test_data_category_statistics_with_dict_input(self):
        """测试类别统计插件 - 字典格式输入"""
        test_data = {
            "raw_data": [
                {"department": "IT", "status": "active"},
                {"department": "HR", "status": "inactive"},
                {"department": "IT", "status": "active"},
                {"department": "Finance", "status": "active"}
            ]
        }
        
        plugin = DataCategoryStatistics("test_category", {
            "config": {
                "column_names": ["department", "status"]
            }
        })
        
        result = plugin.execute(test_data)
        
        self.assertIn("category_statistics", result)
        
        # 验证department统计
        dept_stats = result["category_statistics"]["department"]
        self.assertEqual(dept_stats["total_categories"], 3)
        self.assertEqual(dept_stats["category_counts"]["IT"], 2)
        self.assertEqual(dept_stats["category_counts"]["HR"], 1)
        self.assertEqual(dept_stats["category_counts"]["Finance"], 1)
        self.assertEqual(dept_stats["most_frequent"], "IT")
        
        # 验证status统计
        status_stats = result["category_statistics"]["status"]
        self.assertEqual(status_stats["total_categories"], 2)
        self.assertEqual(status_stats["category_counts"]["active"], 3)
        self.assertEqual(status_stats["category_counts"]["inactive"], 1)
        self.assertEqual(status_stats["most_frequent"], "active")
        
        self.assertEqual(result["category_statistics_check_by"], "test_category")


if __name__ == '__main__':
    # 运行测试
    unittest.main(verbosity=2)